////////////////////////////////////////////////////////////
// Note:
// below code will be moved to ME2FC 2002-4-2 14:56
// Copyright(C) 2002-2005, Leon Cheng , ME2Soft. All rights reserved!
//
// $Id: ME2FCCore.cpp,v 1.1 2008/10/17 06:08:18 leon Exp $ 

#include "ME2FCCore.h"

ME2Str ME2Str::substr(int pos/*0*/,int count/*-1*/) const{
	ME2Str dst;
	if(pos>=m_len) return dst;
	else if(pos<0) pos=0;
	if(count<0||count>m_len-pos) count=m_len-pos;
	dst.assign(m_data+pos,count);
	return dst;		
}		
int ME2Str::find(LPCSTR s,int pos/*0*/,int len/*-1*/) const {
	if(!s) return -1;
	if(len<0) len=strlen(s);
	if(pos<0) pos=0;
	int len1=m_len-pos-len+1;
	for(int i=0;i<len1;i++) {
		if(!clmemcmp(&m_data[i+pos],s,len)) return i+pos;
	}
	return -1;		
}
void ME2Str::ltrim(LPCSTR trim_chars)
{
	int pos;
	for(pos=0;pos<m_len;pos++) {
		if(!strchr(trim_chars,m_data[pos])) break;
	}
	if(pos>0) {
		m_data += pos;
		m_len  -= pos;
	}
}
void ME2Str::rtrim(LPCSTR trim_chars)
{
	int pos;
	for(pos=m_len-1;pos>=0;pos--) {
		if(strchr(trim_chars,m_data[pos])) m_len--;
		else break;
	}
}
int ME2Str::cmp(LPCSTR s,int len/*=-1*/) const {
	if(empty()&&!s) return 0;
	if(len<0) len=strlen(s);
	if(len==0) {
		if(empty()) return 0;
		else return 1;
	} else if(empty()) return -1;
	int ret = clmemcmp(m_data, s, (len < m_len ? len : m_len));
	if(ret) return ret;
	return m_len-len;
}
int ME2Str::find_first_of(LPCSTR s,int pos/*0*/) const {
	if(!s) return -1;
	if(pos<0) pos=0;
	for(int i=pos;i<m_len;i++) {
		if(strchr(s,m_data[i])) return i;
	}
	return -1;	
}

void ME2PtrArray::IncBuf(int growSize/* = 10*/) {
	if(m_size <= m_len) {
		m_size = m_len + growSize;
		void** p = (void**)calloc(m_size, sizeof(void*));
		if(m_len) {
			memcpy(p, m_data, m_len * sizeof(void*));
			free(m_data);
		}
		m_data = p;
	}
}
int	ME2MapStrToPtr::Find(LPCSTR keyName) const {
	for(int i = 0; i < m_len; i++) {
		if(!((ME2MapStrToPtrNode*)m_data[i])->key.cmp(keyName)) return i;
	}
	return -1;
}
int	ME2MapStrToPtr::FindI(LPCSTR keyName) const {
	for(int i = 0; i < m_len; i++) {
		if(!((ME2MapStrToPtrNode*)m_data[i])->key.cmpi(keyName)) return i;
	}
	return -1;
}
void* ME2MapStrToPtr::GetVal(LPCSTR keyName) const {
	int pos = Find(keyName);
	if(pos < 0) return NULL;
	return ((ME2MapStrToPtrNode*)m_data[pos])->val;
}
void* ME2MapStrToPtr::GetValI(LPCSTR keyName) const {
	int pos = FindI(keyName);
	if(pos < 0) return NULL;
	return ((ME2MapStrToPtrNode*)m_data[pos])->val;
}
void ME2MapStrToPtr::AddTail(LPCSTR keyName, void* p) {
	if(!p) return ;
	ME2MapStrToPtrNode* pNode = new ME2MapStrToPtrNode;
	pNode->key = keyName;
	pNode->val = p;
	ME2PtrArray::AddTail(pNode);
}	
int ME2MapStrToStr::GetVal(LPCSTR keyName, CLStr& val) const {
	void* p = ME2MapStrToPtr::GetVal(keyName);
	if(!p) return 0;
	val = *(CLStr*)p;
	return 1;
}
int ME2MapStrToStr::GetValI(LPCSTR keyName, CLStr& val) const {
	void* p = ME2MapStrToPtr::GetValI(keyName);
	if(!p) return 0;
	val = *(CLStr*)p;
	return 1;
}
#ifdef _DEBUG
void ME2MapStrToStr::Dump() {
	for(int i = 0; i < m_len; i++) {
		ME2MapStrToPtrNode* p = (ME2MapStrToPtrNode*)m_data[i];
		printf("%s:%s\n", (LPCSTR)p->key, (LPCSTR)*(CLStr*)p->val);
	}
}
#endif

void* ME2PtrArray::RemoveAt(int pos)
{
	if(pos < 0 || pos >= m_len) return NULL; 
	void* p = m_data[pos];
	if(pos < m_len - 1)	
		memcpy(m_data + pos, m_data + pos + 1, (m_len - pos - 1) * sizeof(void*));
	m_len--;
	return p;
}

void* ME2MapStrToPtr::RemoveAt(int pos)
{
	ME2MapStrToPtrNode* p = (ME2MapStrToPtrNode*) ME2PtrArray::RemoveAt(pos);
	if(!p) return NULL;
	void* ret = p->val;
	delete p;
	return ret;
}

void ME2MapStrToStr::RemoveAt(int pos)
{
	CLStr* p = (CLStr*)ME2MapStrToPtr::RemoveAt(pos);
	if(p) delete p;
}

void* ME2MapStrToPtr::SetVal(LPCSTR keyName, void* val)
{
	int pos = Find(keyName);
	if(pos < 0) {
		if(val) AddTail(keyName, val);
		return NULL;
	} 
	if(val) {
		void* ret = ((ME2MapStrToPtrNode*)m_data[pos])->val;
		if(val) ((ME2MapStrToPtrNode*)m_data[pos])->val = val;
		return ret;
	} else return RemoveAt(pos);
}

void* ME2MapStrToPtr::SetValI(LPCSTR keyName, void *val)
{
	int pos = FindI(keyName);
	if(pos < 0) {
		if(val) AddTail(keyName, val);
		return NULL;
	} 
	if(val) {
		void* ret = ((ME2MapStrToPtrNode*)m_data[pos])->val;
		((ME2MapStrToPtrNode*)m_data[pos])->val = val;
		return ret;
	} else return RemoveAt(pos);
}

void ME2MapStrToStr::SetVal(LPCSTR key, LPCSTR val)
{
	CLStr* p;
	if(val) p = (CLStr*)ME2MapStrToPtr::SetVal(key, new CLStr(val));
	else p = (CLStr*)ME2MapStrToPtr::SetVal(key, NULL);
	if(p) delete p;
}

void ME2MapStrToStr::SetValI(LPCSTR key, LPCSTR val)
{
	CLStr* p;
	if(val) p = (CLStr*)ME2MapStrToPtr::SetValI(key, new CLStr(val));
	else p = (CLStr*)ME2MapStrToPtr::SetValI(key, NULL);
	if(p) delete p;
}
